package com.zmn.oms.business.interfaces.orderstock;

import cn.hutool.core.date.DatePattern;
import com.alibaba.fastjson.JSON;
import com.alibaba.nacos.api.config.annotation.NacosValue;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.zmn.base.product.common.consts.BaseProductConsts;
import com.zmn.base.product.common.dto.categ.CategProductGroupDRO;
import com.zmn.base.product.common.query.categ.CategProductGroupQuery;
import com.zmn.base.product.dubbo.interfaces.categ.serv.CategServProductListRemoteService;
import com.zmn.common.constant.GlobalConsts;
import com.zmn.common.dto2.ResponseDTO;
import com.zmn.common.utils.collection.CollectionUtil;
import com.zmn.common.utils.date.DateUtil;
import com.zmn.common.utils.number.NumberUtil;
import com.zmn.common.utils.string.StringUtil;
import com.zmn.engstock.common.model.dio.EngineerStockItemDIO;
import com.zmn.engstock.common.model.dio.RoutePlanDIO;
import com.zmn.engstock.common.model.dio.StockItemDIO;
import com.zmn.engstock.common.model.dio.TakeUpStockDIO;
import com.zmn.engstock.common.model.dro.EngineerStockItemDRO;
import com.zmn.engstock.common.model.dro.RoutePlanDRO;
import com.zmn.engstock.common.model.dro.StockItemDRO;
import com.zmn.engstock.common.model.dro.StockUsedDRO;
import com.zmn.engstock.common.model.dro.stock.StockUsedOrderDetailDRO;
import com.zmn.engstock.common.model.query.stock.StockUsedQuery;
import com.zmn.engstock.dubbo.interfaces.stock.StockListRemoteService;
import com.zmn.engstock.dubbo.interfaces.stock.StockModifyRemoteService;
import com.zmn.oms.common.constant.OrderTagConsts;
import com.zmn.oms.common.enums.MasterStockTypeEnum;
import com.zmn.oms.common.exception.OmsBaseException;
import com.zmn.oms.model.bo.stock.DistributeMasterStockBO;
import com.zmn.oms.model.bo.stock.MasterStockQueryBO;
import com.zmn.oms.model.bo.stock.QueryUsableStockBO;
import com.zmn.oms.model.dto.orderstock.CheckLockStockDTO;
import com.zmn.oms.model.dto.orderstock.LockStockDTO;
import com.zmn.oms.model.dto.orderstock.ReleaseStockDTO;
import com.zmn.oms.model.dto.orderstock.StockWhiteDTO;
import com.zmn.oms.model.entity.omstrack.OrderWorkTrack;
import com.zmn.oms.model.entity.product.OrderProduct;
import com.zmn.oms.model.entity.tag.OrderTag;
import com.zmn.oms.model.entity.work.OrderWork;
import com.zmn.oms.services.interfaces.product.OrderProductService;
import com.zmn.oms.services.interfaces.tag.OrderTagService;
import com.zmn.oms.services.interfaces.work.OrderWorkService;
import com.zmn.oms.services.interfaces.worktrack.WorkTrackService;
import com.zmn.track.common.constant.TrackConsts;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.Reference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 类描述：订单库存
 *
 * @author heciqi
 * @date 2020/05/07 16:36
 */
@Slf4j
@Service
public class OrderStockBServiceImpl implements OrderStockBService {

	// 释放库存限定内容ids
	private final static List<Integer> RELEASE_STOCK_RESTRICT_TRACK_CONTENT_IDS = Lists.newArrayList(
			TrackConsts.TRACK_CONTENT_ID_SERVICE_COMPLETE,
			TrackConsts.TRACK_CONTENT_ID_REWORK,
			TrackConsts.TRACK_CONTENT_ID_COMPANY_MONEY,
			TrackConsts.TRACK_CONTENT_ID_PLAT_MONEY
	);

	@Autowired
	private OrderWorkService orderWorkService;
	@Autowired
	private OrderProductService orderProductService;
	@Autowired
	private WorkTrackService workTrackService;
	@Autowired
	private OrderTagService orderTagService;

	@Reference(version = com.zmn.base.plat.engine.common.constant.DubboConsts.INTERFACE_VERSION , check = false)
	private StockListRemoteService stockListRemoteService;
	@Reference(version = com.zmn.base.plat.engine.common.constant.DubboConsts.INTERFACE_VERSION , check = false)
	private StockModifyRemoteService stockModifyRemoteService;
	@Reference(version = com.zmn.base.plat.engine.common.constant.DubboConsts.INTERFACE_VERSION , check = false)
	protected CategServProductListRemoteService categServProductListRemoteService;

	@NacosValue(value = "${stock.masterid}", autoRefreshed = true)
	private String stockMasterIdList;

	@NacosValue(value = "${stock.city}", autoRefreshed = true)
	private String stockCity;

	/**
	 * 查询工程师库存
	 *
	 * @param curDate          日期
	 * @param engineerId       工程师ID
	 * @param productGroupCode 产品组CODE
	 * @param productNum       产品数量
	 * @param workId           工单id（用于是否排除本单已锁定库存）
	 * @return
	 */
	@Override
	public List<StockItemDRO> getStockByEngineerIdAndProductGroupId(String curDate, Integer engineerId, Integer productGroupCode, Integer productNum, Long workId) {
		StockItemDIO stockItemDIO = new StockItemDIO();
		stockItemDIO.setDate(cn.hutool.core.date.DateUtil.parseLocalDateTime(curDate, DatePattern.NORM_DATE_PATTERN).toLocalDate());
		stockItemDIO.setEngineerId(engineerId);
		stockItemDIO.setProductGroupCode(productGroupCode);
		stockItemDIO.setProductNum(productNum);
		log.info("查询库存 入参：{}", JSON.toJSONString(stockItemDIO));
		ResponseDTO<List<StockItemDRO>> responseDTO = stockListRemoteService.getStockByEngineerAndProduct(stockItemDIO, NumberUtil.isNullOrZero(workId) ? null : String.valueOf(workId));
		log.info("查询库存 出参：{}", JSON.toJSONString(responseDTO));

		if (!responseDTO.isSuccess()) {
			return Lists.newArrayList();
		}

//		List<StockItemDRO> list = Lists.newArrayList();
//		list.add(StockItemDRO.builder().startTime(LocalTime.of(19, 23)).endTime(LocalTime.of(21, 40))
//				.build());
//		list.add(StockItemDRO.builder().startTime(LocalTime.of(22, 31)).endTime(LocalTime.of(22, 55))
//				.build());
		return responseDTO.getData();
	}

	/**
	 * 重新锁定库存
	 * 如果没有锁定，则不锁
	 *
	 * @param lockStockDTO
	 * @throws OmsBaseException
	 */
	@Override
	public void reLockEngStock(LockStockDTO lockStockDTO) throws OmsBaseException {
		OrderWork newestOrderWork = orderWorkService.findOrderWorkByKeySrcMaster(lockStockDTO.getOrderId(), lockStockDTO.getWorkId());

		CheckLockStockDTO checkLockStockDTO = this.getCheckLockStockDTO(newestOrderWork);

		if (NumberUtil.isNotNullOrZero(lockStockDTO.getMasterId())) {
			checkLockStockDTO.setMasterId(lockStockDTO.getMasterId());
		}

		boolean isLockStock = this.checkIsLockStock(checkLockStockDTO);
		if (!isLockStock) {
			return;
		}

		// 产品
		List<OrderProduct> orderProducts = orderProductService.listOrderProductByOrderId(newestOrderWork.getOrderId());
		if (CollectionUtil.isNullOrEmpty(orderProducts)) {
			return;
		}

		// 如果未占用过库存-不处理
		boolean isExit = this.checkExitOrder(newestOrderWork.getWorkId(), checkLockStockDTO.getMasterId());
		if (!isExit) {
			return;
		}

		QueryUsableStockBO queryUsableStockBO = QueryUsableStockBO
				.builder()
				.bizType(newestOrderWork.getBizType())
				.servCategId(newestOrderWork.getServCategId())
				.showCategId(newestOrderWork.getShowCategId())
				.dutyTime(newestOrderWork.getDutyTime())
				.isExcludeThisOrder(true)
				.masterId(newestOrderWork.getMasterId())
				.number(orderProducts.get(0).getNumber())
				.workId(newestOrderWork.getWorkId())
				.build();
		TakeUpStockDIO taskUpStock = this.getTaskUpStock(queryUsableStockBO);
		String bizId = String.valueOf(newestOrderWork.getWorkId());
		log.info("调用重新锁库存接口 入参：bizType={},masterId={},taskUpStock={}", bizId, checkLockStockDTO.getMasterId(), JSON.toJSONString(taskUpStock));
		ResponseDTO<StockItemDRO> responseDTO = stockModifyRemoteService.reloadStockByTime(bizId, checkLockStockDTO.getMasterId(), null, taskUpStock);
		log.info("调用重新锁库存接口 出参：{}", JSON.toJSONString(responseDTO));
		if (!responseDTO.isSuccess()) {
			throw new OmsBaseException("重新占用库存失败");
		}
	}

	@Override
	public void releaseStock(ReleaseStockDTO releaseStockDTO) throws OmsBaseException {
		StockWhiteDTO stockWhiteDTO = StockWhiteDTO.builder()
				.masterId(releaseStockDTO.getMasterId())
				.workCityId(releaseStockDTO.getCityId())
				.build();
		boolean whiteByAllConditions = this.isWhiteByAllConditions(stockWhiteDTO);
		if (!whiteByAllConditions) {
			return;
		}
		String bizId = String.valueOf(releaseStockDTO.getWorkId());
		log.info("调用释放库存接口 入参：bizId={}，masterId={}", bizId, releaseStockDTO.getMasterId());
		ResponseDTO<Boolean> responseDTO = stockModifyRemoteService.releaseStockByBizId(bizId, releaseStockDTO.getMasterId(), null);
		log.info("调用释放库存接口 出参：{}", JSON.toJSONString(responseDTO));
		if (!responseDTO.isSuccess()) {
			throw new OmsBaseException(String.format("%s：%s", "释放占用库存失败", responseDTO.getMessage()));
		}
	}

	@Override
	public void releaseStock(Long orderId, Long workId) throws OmsBaseException {
		OrderWork orderWork = orderWorkService.findOrderWorkByKey(orderId, workId);
		ReleaseStockDTO releaseStockDTO = new ReleaseStockDTO();
		releaseStockDTO.setOrderId(orderWork.getOrderId());
		releaseStockDTO.setWorkId(orderWork.getWorkId());
		releaseStockDTO.setMasterId(orderWork.getMasterId());
		releaseStockDTO.setCityId(orderWork.getCityId());
		this.releaseStock(releaseStockDTO);
	}

	private TakeUpStockDIO getTaskUpStock(QueryUsableStockBO queryUsableStockBO) throws OmsBaseException {
		Integer productGroupCode = 0;
		String productGroupName = "";
		// 查询产品组
		log.info("servAssCategoryListRemoteService#getProductGroupByShowCategId 查询产品分组 入参：servCateg={}, categTwoId={}", queryUsableStockBO.getServCategId(), queryUsableStockBO.getShowCategId());
		CategProductGroupQuery categProductGroupQuery = new CategProductGroupQuery();
		categProductGroupQuery.setServCategId(queryUsableStockBO.getServCategId());
		categProductGroupQuery.setCategId(queryUsableStockBO.getShowCategId());
		categProductGroupQuery.setBizType(queryUsableStockBO.getBizType());
		categProductGroupQuery.setShowType(BaseProductConsts.EC_SHOW_TYPE);
		ResponseDTO<CategProductGroupDRO> responseDTO = categServProductListRemoteService.getBasisProductGroupByQuery(categProductGroupQuery);
		log.info("servAssCategoryListRemoteService#getProductGroupByShowCategId 查询产品分组 出参：【{}】", responseDTO);
		CategProductGroupDRO categorySimpleProductGroupDRO = responseDTO.getData();
		if (categorySimpleProductGroupDRO != null) {
			productGroupCode = categorySimpleProductGroupDRO.getGroupCode();
			productGroupName = categorySimpleProductGroupDRO.getName();
		}

		// 过滤库存开始时间&库存结束时间
		DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("HH:mm");
		List<StockItemDRO> stockItemDROS = this.getStockByEngineerIdAndProductGroupId(DateUtil.toString(queryUsableStockBO.getDutyTime(), DateUtil.FORMAT_DATE), queryUsableStockBO.getMasterId(), productGroupCode, queryUsableStockBO.getNumber(), queryUsableStockBO.isExcludeThisOrder() ? queryUsableStockBO.getWorkId() : null);
		LocalDateTime localDateTime = cn.hutool.core.date.DateUtil.toLocalDateTime(queryUsableStockBO.getDutyTime());
		LocalTime localTime = localDateTime.toLocalTime();
		StockItemDRO stockItem = null;
		for (StockItemDRO stockItemDRO : stockItemDROS) {
			for (String time : stockItemDRO.getTimeList()) {
				String[] split = time.split(" - ");
				LocalTime startTime = LocalTime.parse(split[0], dateTimeFormatter);
				LocalTime endTime = LocalTime.parse(split[1], dateTimeFormatter);
				if ((startTime.compareTo(localTime) == 0 || startTime.isBefore(localTime)) && (endTime.compareTo(localTime) == 0 || endTime.isAfter(localTime))) {
					stockItem = stockItemDRO;
					break;
				}
			}
			if (Objects.nonNull(stockItem)) {
				break;
			}
		}

		// 派单占用库存（没有最佳时间就取最后一个库存进行占用）
		if (queryUsableStockBO.isDistributeLockStock() && Objects.isNull(stockItem) && CollectionUtil.isNotNullOrEmpty(stockItemDROS)) {
			stockItem = stockItemDROS.get(stockItemDROS.size() - 1);
		}

		if (Objects.isNull(stockItem)) {
			throw new OmsBaseException("服务时间冲突，请选择其他服务时间");
		}

		return TakeUpStockDIO.builder()
				.bizId(String.valueOf(queryUsableStockBO.getWorkId()))
				// 杨宽说目前写死为1
				.bizType(GlobalConsts.NO)
				.engineerId(queryUsableStockBO.getMasterId())
				.productGroupCode(productGroupCode)
				.productGroupName(productGroupName)
				.date(localDateTime.toLocalDate())
				.startTime(LocalTime.parse(stockItem.getStartTime(), dateTimeFormatter))
				.endTime(LocalTime.parse(stockItem.getEndTime(), dateTimeFormatter))
				.build();
	}

	@Override
	public boolean isWhiteMasterId(Integer masterId){
		if (NumberUtil.isNullOrZero(masterId)) {
			return false;
		}

		if (StringUtil.isBlank(stockMasterIdList)) {
			return true;
		}

		List<String> strings = Arrays.asList(stockMasterIdList.split(","));
		return strings.contains(String.valueOf(masterId));
	}

	@Override
	public boolean isWhiteWorkCity(Integer cityId) {
		if (NumberUtil.isNullOrZero(cityId)) {
			return false;
		}
		if (StringUtil.isBlank(stockCity)) {
			return true;
		}
		List<String> strings = Arrays.asList(stockCity.split(","));
		return strings.contains(String.valueOf(cityId));
	}

	@Override
	public boolean isWhiteByAllConditions(StockWhiteDTO stockWhiteDTO) {
		if (NumberUtil.isNullOrZero(stockWhiteDTO.getMasterId())) {
			return false;
		}

		return this.isWhiteWorkCity(stockWhiteDTO.getWorkCityId()) || this.isWhiteMasterId(stockWhiteDTO.getMasterId());
	}

	/**
	 * 检查是否占用过库存
	 *
	 * @param workId
	 * @param engineerId
	 * @return
	 */
	@Override
	public boolean checkExitOrder(Long workId, Integer engineerId) throws OmsBaseException {
		log.info("stockListRemoteService.checkExitOrder 入参：engineerId={}，workId={}", engineerId, workId);
		ResponseDTO<Boolean> responseDTO = stockListRemoteService.checkExitOrder(engineerId, String.valueOf(workId));
		log.info("stockListRemoteService.checkExitOrder 出参：responseDTO={}", responseDTO);
		if (!responseDTO.isSuccess()) {
			throw new OmsBaseException(responseDTO.getMessage());
		}
		return responseDTO.getData();
	}

	/**
	 * 占用库存
	 * @param lockStockDTO
	 */

	@Override
	public void takeUpStock(LockStockDTO lockStockDTO) throws OmsBaseException {
		OrderWork newestOrderWork = orderWorkService.findOrderWorkByKeySrcMaster(lockStockDTO.getOrderId(), lockStockDTO.getWorkId());
		this.takeUpStock(lockStockDTO, newestOrderWork);
	}

	@Override
	public void takeUpStock(LockStockDTO lockStockDTO, OrderWork newestOrderWork) throws OmsBaseException {
		log.info("OrderStockBServiceImpl.takeUpStock orderId={}", newestOrderWork.getOrderId());
		CheckLockStockDTO checkLockStockDTO = this.getCheckLockStockDTO(newestOrderWork);

		if (NumberUtil.isNotNullOrZero(lockStockDTO.getMasterId())) {
			checkLockStockDTO.setMasterId(lockStockDTO.getMasterId());
		}

		boolean isLockStock = this.checkIsLockStock(checkLockStockDTO);
		if (!isLockStock) {
			return;
		}

		List<OrderProduct> orderProducts = orderProductService.listOrderProductByOrderId(newestOrderWork.getOrderId());
		if (CollectionUtil.isNullOrEmpty(orderProducts)) {
			return;
		}

		// 手机端占用库存过滤
		if (lockStockDTO.isMobileLockStock()) {
			RoutePlanDIO routePlanDIO = new RoutePlanDIO();
			routePlanDIO.setEngineerId(checkLockStockDTO.getMasterId());
			routePlanDIO.setProductGroupId(newestOrderWork.getServProductGroupId());
			routePlanDIO.setDate(DateUtil.toString(newestOrderWork.getDutyTime(), DateUtil.FORMAT_DATE));
			routePlanDIO.setProductNum(orderProducts.get(0).getNumber());
			log.info("stockListRemoteService.getRoutePlanInfoByEngineerAndProduct routePlanDIO={}", JSON.toJSONString(routePlanDIO));
			ResponseDTO<RoutePlanDRO> responseDTO = stockListRemoteService.getRoutePlanInfoByEngineerAndProduct(routePlanDIO);
			log.info("stockListRemoteService.getRoutePlanInfoByEngineerAndProduct responseDTO={}", JSON.toJSONString(responseDTO));
			if (!responseDTO.isSuccess()) {
				throw new OmsBaseException(responseDTO.getMessage());
			}
			List<StockUsedDRO> stockUsedDROList = responseDTO.getData().getStockUsedDROList();
			if (CollectionUtil.isNotNullOrEmpty(stockUsedDROList)) {
				StockUsedDRO stockUsedDRO = stockUsedDROList.stream()
						.filter(e -> Objects.equals(e.getOrderId(), String.valueOf(newestOrderWork.getWorkId())))
						.findAny()
						.orElse(null);
				if (Objects.nonNull(stockUsedDRO)) {
					List<String> timeList = stockUsedDRO.getTimeList();
					if (CollectionUtil.isNotNullOrEmpty(timeList)) {
						// 说明占用过就不用占用了
						for (String time : timeList) {
							int dutyTime = Integer.parseInt(DateUtil.toString(newestOrderWork.getDutyTime(), "HH:mm").replace(":", ""));
							int startTime = Integer.parseInt(time.substring(0, time.indexOf(" ")).replace(":", ""));
							int endTime = Integer.parseInt(time.substring(time.lastIndexOf(" ") + 1).replace(":", ""));
							if (dutyTime >= startTime && dutyTime <= endTime) {
								return;
							}
						}
					}
				}
			}
		}

		QueryUsableStockBO queryUsableStockBO = QueryUsableStockBO
				.builder()
				.bizType(newestOrderWork.getBizType())
				.servCategId(newestOrderWork.getServCategId())
				.showCategId(newestOrderWork.getShowCategId())
				// 没有预约时间取当前时间
				.dutyTime(Objects.isNull(newestOrderWork.getDutyTime()) ? DateUtil.getNow() : newestOrderWork.getDutyTime())
				.isExcludeThisOrder(lockStockDTO.isExcludeThisOrder())
				.masterId(checkLockStockDTO.getMasterId())
				.number(orderProducts.get(0).getNumber())
				.workId(newestOrderWork.getWorkId())
				.isDistributeLockStock(lockStockDTO.isDistributeLockStock())
				.build();

		TakeUpStockDIO taskUpStock = null;
		try {
			taskUpStock = this.getTaskUpStock(queryUsableStockBO);
		} catch (OmsBaseException e) {
			// 如果是派单占用库存，则不抛出异常
			if (lockStockDTO.isDistributeLockStock()) {
				return;
			}else {
				throw e;
			}
		}

		// 占用过库存-重新占用库存
		boolean isExit = this.checkExitOrder(newestOrderWork.getWorkId(), checkLockStockDTO.getMasterId());

		if (isExit) {
			String bizId = String.valueOf(newestOrderWork.getWorkId());
			log.info("调用重新锁库存接口 入参：bizType={},masterId={},taskUpStock={}", bizId, checkLockStockDTO.getMasterId(), JSON.toJSONString(taskUpStock));
			ResponseDTO<StockItemDRO> responseDTO = stockModifyRemoteService.reloadStockByTime(bizId, checkLockStockDTO.getMasterId(), null, taskUpStock);
			log.info("调用重新锁库存接口 出参：{}", JSON.toJSONString(responseDTO));
			if (!responseDTO.isSuccess()) {
				// 如果是派单占用库存，则不抛出异常
				if (!lockStockDTO.isDistributeLockStock()) {
					throw new OmsBaseException("重新占用库存失败");
				}
			}
		} else {
			log.info("调用锁库存接口 入参：{}", JSON.toJSONString(taskUpStock));
			ResponseDTO<Boolean> responseDTO = stockModifyRemoteService.takeUpStock(taskUpStock);
			log.info("调用锁库存接口 出参：{}", JSON.toJSONString(responseDTO));
			if (!responseDTO.isSuccess()) {
				// 如果是派单占用库存，则不抛出异常
				if (!lockStockDTO.isDistributeLockStock()) {
					throw new OmsBaseException("占用库存失败");
				}
			}
		}
	}

	/**
	 * 检查是否需要锁库存
	 *
	 * @param checkLockStockDTO
	 * @return true 需要锁定库存
	 * @throws OmsBaseException
	 */
	@Override
	public boolean checkIsLockStock(CheckLockStockDTO checkLockStockDTO) {
		StockWhiteDTO stockWhiteDTO = StockWhiteDTO.builder()
				.workCityId(checkLockStockDTO.getCityId())
				.masterId(checkLockStockDTO.getMasterId())
				.build();
		boolean whiteByAllConditions = this.isWhiteByAllConditions(stockWhiteDTO);
		if (!whiteByAllConditions) {
			return false;
		}

		// 测试单不占用库存
		if (Objects.equals(checkLockStockDTO.getTest(), GlobalConsts.YES)) {
			return false;
		}

		// 重复单不占用库存
		if (Objects.equals(checkLockStockDTO.getDuplicate(), GlobalConsts.YES)) {
			return false;
		}

		// 跟单触发释放库存，再发起占用请求不处理
//		List<OrderWorkTrack> workTrackList = workTrackService.getWorkTrackByTrackTypeList(checkLockStockDTO.getOrderId(), checkLockStockDTO.getWorkId(), RELEASE_STOCK_RESTRICT_TRACK_CONTENT_IDS);
//		if (CollectionUtil.isNotNullOrEmpty(workTrackList)) {
//			return false;
//		}

		// 特殊跟单，不占用库存
		if (CollectionUtil.isNotNullOrEmpty(checkLockStockDTO.getWorkTrackList())) {
			Optional<OrderWorkTrack> first = checkLockStockDTO.getWorkTrackList().stream()
					.filter(e -> RELEASE_STOCK_RESTRICT_TRACK_CONTENT_IDS.contains(e.getTrackType()))
					.findAny();
			if (first.isPresent()) {
				return false;
			}
		}

		// 竞争工单 再发起占用请求不处理
		// List<OrderTag> orderTags = orderTagService.listOrderTagByOrderId(checkLockStockDTO.getOrderId(), checkLockStockDTO.getWorkId());
		if (CollectionUtil.isNotNullOrEmpty(checkLockStockDTO.getOrderTagList())) {
			Optional<OrderTag> first = checkLockStockDTO.getOrderTagList().stream()
					.filter(e -> Objects.equals(e.getTagId(), OrderTagConsts.TAG_ID_WORK_COMPETITION))
					.findAny();
			if (first.isPresent()) {
				return false;
			}
		}

		return true;
	}

	/**
	 * 获取DTO
	 *
	 * @param orderWork
	 * @return
	 */
	@Override
	public CheckLockStockDTO getCheckLockStockDTO(OrderWork orderWork) {
		CheckLockStockDTO checkLockStockDTO = new CheckLockStockDTO();
		checkLockStockDTO.setOrderId(orderWork.getOrderId());
		checkLockStockDTO.setWorkId(orderWork.getWorkId());
		checkLockStockDTO.setDuplicate(orderWork.getDuplicate());
		checkLockStockDTO.setTest(orderWork.getTest());
		checkLockStockDTO.setMasterId(orderWork.getMasterId());
		checkLockStockDTO.setCityId(orderWork.getCityId());

		List<OrderWorkTrack> workTrackList = workTrackService.queryListByOrderIdSrcMaster(orderWork.getOrderId(), orderWork.getWorkId());
		checkLockStockDTO.setWorkTrackList(workTrackList);

		List<OrderTag> orderTagList = orderTagService.listOrderTagByOrderId(checkLockStockDTO.getOrderId(), checkLockStockDTO.getWorkId());
		checkLockStockDTO.setOrderTagList(orderTagList);
		return checkLockStockDTO;
	}

	@Override
	public List<Integer> releaseStockRestrictTrackContentIds(){
		return RELEASE_STOCK_RESTRICT_TRACK_CONTENT_IDS;
	}


	@Override
	public Map<Integer, Integer> canDistributeMaster(DistributeMasterStockBO distributeMasterStockBO) {
		log.info("OrderStockBServiceImpl.canDistributeMaster distributeMasterStockBO={}", distributeMasterStockBO);

		if (CollectionUtil.isNullOrEmpty(distributeMasterStockBO.getEngineerIdList())) {
			return Maps.newHashMap();
		}

		// 没有时间 默认当天
		if (Objects.isNull(distributeMasterStockBO.getDutyTime())) {
			distributeMasterStockBO.setDutyTime(DateUtil.getNow());
		}

		// 处理参数
		this.processDistributeMasterBO(distributeMasterStockBO);

		// 产品组code
		Integer productGroupCode = 0;
		// 查询产品组
		log.info("servAssCategoryListRemoteService#getProductGroupByShowCategId 查询产品分组 入参：servCateg={}, categTwoId={}", distributeMasterStockBO.getServCategId(), distributeMasterStockBO.getShowCategId());
		CategProductGroupQuery categProductGroupQuery = new CategProductGroupQuery();
		categProductGroupQuery.setServCategId(distributeMasterStockBO.getServCategId());
		categProductGroupQuery.setCategId(distributeMasterStockBO.getShowCategId());
		categProductGroupQuery.setBizType(distributeMasterStockBO.getBizType());
		categProductGroupQuery.setShowType(BaseProductConsts.EC_SHOW_TYPE);
		ResponseDTO<CategProductGroupDRO> responseDTO = categServProductListRemoteService.getBasisProductGroupByQuery(categProductGroupQuery);
		log.info("servAssCategoryListRemoteService#getProductGroupByShowCategId 查询产品分组 出参：【{}】", responseDTO);
		CategProductGroupDRO categorySimpleProductGroupDRO = responseDTO.getData();
		if (categorySimpleProductGroupDRO != null) {
			productGroupCode = categorySimpleProductGroupDRO.getGroupCode();
		}


		HashMap<Integer, Integer> masterMap = Maps.newHashMapWithExpectedSize(distributeMasterStockBO.getEngineerIdList().size());

		List<Integer> stockWhiteMasterIdList = new ArrayList<>();
		for (Integer masterId : distributeMasterStockBO.getEngineerIdList()) {
			// 默认都是最优库存
			masterMap.put(masterId, MasterStockTypeEnum.OPTIMAL_STOCK.getCode());
			StockWhiteDTO stockWhiteDTO = StockWhiteDTO.builder()
					.masterId(masterId)
					.workCityId(distributeMasterStockBO.getCityId())
					.build();
			boolean whiteByAllConditions = this.isWhiteByAllConditions(stockWhiteDTO);
			if (whiteByAllConditions) {
				stockWhiteMasterIdList.add(masterId);
			}
		}

		if (CollectionUtil.isNullOrEmpty(stockWhiteMasterIdList)) {
			return masterMap;
		}

		// 校验工程师库存量
		LocalDate dutyTime = LocalDate.parse(DateUtil.toString(distributeMasterStockBO.getDutyTime(), DateUtil.FORMAT_DATE), DateTimeFormatter.ofPattern(DateUtil.FORMAT_DATE));
		List<List<Integer>> partition = Lists.partition(stockWhiteMasterIdList, 200);
		int dutyTimeInt = Integer.parseInt(DateUtil.toString(distributeMasterStockBO.getDutyTime(), "HH:mm").replace(":", ""));

		EngineerStockItemDIO engineerStockItemDIO = new EngineerStockItemDIO();
		engineerStockItemDIO.setDate(dutyTime);
		engineerStockItemDIO.setProductGroupCode(productGroupCode);
		engineerStockItemDIO.setProductNum(distributeMasterStockBO.getProductNumber());
		try {
			for (List<Integer> masterIdList : partition) {
				log.info("stockListRemoteService.listStockByEngineerIdListAndProduct engineerStockItemDIO={},masterIdList={}", engineerStockItemDIO, masterIdList);
				ResponseDTO<List<EngineerStockItemDRO>> listResponseDTO = stockListRemoteService.listStockByEngineerIdListAndProduct(engineerStockItemDIO, masterIdList);
				log.info("stockListRemoteService.listStockByEngineerIdListAndProduct listResponseDTO={}", listResponseDTO);
				if (CollectionUtil.isNullOrEmpty(listResponseDTO.getData())) {
					for (Integer masterId : masterIdList) {
						masterMap.put(masterId, MasterStockTypeEnum.NO_STOCK.getCode());
					}
					continue;
				}

				Map<Integer, EngineerStockItemDRO> masterStockMap = Maps.uniqueIndex(listResponseDTO.getData(), EngineerStockItemDRO::getEngineerId);
				for (Integer masterId : masterIdList) {
					EngineerStockItemDRO engineerStockItemDRO = masterStockMap.get(masterId);
					if (Objects.isNull(engineerStockItemDRO) || CollectionUtil.isNullOrEmpty(engineerStockItemDRO.getStockItemDRO())) {
						masterMap.put(masterId, MasterStockTypeEnum.NO_STOCK.getCode());
						continue;
					}

					// 有库存
					masterMap.put(masterId, MasterStockTypeEnum.HAVE_STOCK.getCode());

					// HH:mm 比较 找最优库存
					boolean isStop = false;
					List<StockItemDRO> stockItemDRO = engineerStockItemDRO.getStockItemDRO();
					for (StockItemDRO stockItemDro : stockItemDRO) {
						if (CollectionUtil.isNullOrEmpty(stockItemDro.getTimeList())) {
							continue;
						}
						for (String time : stockItemDro.getTimeList()) {
							String[] split = time.split(" - ");
							int startTime = Integer.parseInt(split[0].replace(":", ""));
							int endTime = Integer.parseInt(split[1].replace(":", ""));
							if (dutyTimeInt >= startTime && dutyTimeInt <= endTime) {
								masterMap.put(masterId, MasterStockTypeEnum.OPTIMAL_STOCK.getCode());
								isStop = true;
								break;
							}
						}
						if (isStop) {
							break;
						}
					}
				}
			}
		} catch (Exception e) {
			log.error("e={}", e);
		}
		return masterMap;
	}

	private void processDistributeMasterBO(DistributeMasterStockBO distributeMasterStockBO){
		if (NumberUtil.isNullOrZero(distributeMasterStockBO.getOrderId()) || NumberUtil.isNullOrZero(distributeMasterStockBO.getWorkId())) {
			return;
		}
		OrderWork orderWork = orderWorkService.findOrderWorkByKey(distributeMasterStockBO.getOrderId(), distributeMasterStockBO.getWorkId());
		// 产品数量
		Integer productNumber = null;
		List<OrderProduct> orderProductList = orderProductService.listOrderProductByOrderId(distributeMasterStockBO.getOrderId());
		if (CollectionUtil.isNotNullOrEmpty(orderProductList)) {
			productNumber = orderProductList.get(0).getNumber();
		}

		distributeMasterStockBO.setProductNumber(productNumber);
		distributeMasterStockBO.setBizType(orderWork.getBizType());
		distributeMasterStockBO.setCityId(orderWork.getCityId());
		distributeMasterStockBO.setServCategId(orderWork.getServCategId());
		distributeMasterStockBO.setShowCategId(orderWork.getShowCategId());
	}

	@Override
	public boolean isStockOverdue(Long orderId, Long workId) throws OmsBaseException {
		log.info("isStockOverdue orderId={},workId={}", orderId, workId);
		OrderWork newestOrderWork = orderWorkService.findOrderWorkByKey(orderId, workId);

		// 未占用过当作 未过期处理
		boolean checkExitOrder = this.checkExitOrder(workId, newestOrderWork.getMasterId());
		if (!checkExitOrder) {
			return false;
		}
		log.info("stockListRemoteService.checkOutOfDate masterId={},workId={}", newestOrderWork.getMasterId(), newestOrderWork.getWorkId());
		ResponseDTO<Boolean> responseDTO = stockListRemoteService.checkOutOfDate(newestOrderWork.getMasterId(), String.valueOf(workId));
		log.info("stockListRemoteService.checkOutOfDate responseDTO={}", responseDTO);
		if (!responseDTO.isSuccess()) {
			throw new OmsBaseException(responseDTO.getMessage());
		}
		return responseDTO.getData();
	}

	@Override
	public Set<Integer> getStockMasterIdList(){
		if (StringUtil.isBlank(stockMasterIdList)) {
			return null;
		}
		return Arrays.stream(stockMasterIdList.split(","))
				.map(Integer::parseInt)
				.collect(Collectors.toSet());
	}

	@Override
	public Map<Integer, List<StockItemDRO>> listMasterStock(MasterStockQueryBO masterStockQueryBO) {
		log.info("listMasterStock masterStockQueryBO={}", masterStockQueryBO);
		if (CollectionUtil.isNullOrEmpty(masterStockQueryBO.getEngineerIdList())) {
			return Maps.newHashMap();
		}
		// 没有时间 默认当天
		if (Objects.isNull(masterStockQueryBO.getDutyTime())) {
			masterStockQueryBO.setDutyTime(DateUtil.getNow());
		}

		// 大于15天之后的日期不处理 TODO wyc 临时处理
		int maxDay = Integer.parseInt(DateUtil.toString(DateUtil.addDays(DateUtil.getNow(), 15), DateUtil.FORMAT_DATE2));
		int dutyDay = Integer.parseInt(DateUtil.toString(masterStockQueryBO.getDutyTime(), DateUtil.FORMAT_DATE2));
		if (dutyDay > maxDay) {
			return Maps.newHashMap();
		}

		// 产品组code
		Integer productGroupCode = 0;
		// 查询产品组
		log.info("servAssCategoryListRemoteService#getProductGroupByShowCategId 查询产品分组 入参：servCateg={}, categTwoId={}", masterStockQueryBO.getServCategId(), masterStockQueryBO.getShowCategId());
		CategProductGroupQuery categProductGroupQuery = new CategProductGroupQuery();
		categProductGroupQuery.setServCategId(masterStockQueryBO.getServCategId());
		categProductGroupQuery.setCategId(masterStockQueryBO.getShowCategId());
		categProductGroupQuery.setBizType(masterStockQueryBO.getBizType());
		categProductGroupQuery.setShowType(BaseProductConsts.EC_SHOW_TYPE);
		ResponseDTO<CategProductGroupDRO> responseDTO = categServProductListRemoteService.getBasisProductGroupByQuery(categProductGroupQuery);
		log.info("servAssCategoryListRemoteService#getProductGroupByShowCategId 查询产品分组 出参：【{}】", responseDTO);
		CategProductGroupDRO categorySimpleProductGroupDRO = responseDTO.getData();
		if (categorySimpleProductGroupDRO != null) {
			productGroupCode = categorySimpleProductGroupDRO.getGroupCode();
		}
		Map<Integer, List<StockItemDRO>> masterStockMap = Maps.newHashMapWithExpectedSize(masterStockQueryBO.getEngineerIdList().size());
		List<Integer> stockWhiteMasterIdList = new ArrayList<>();
		for (Integer masterId : masterStockQueryBO.getEngineerIdList()) {
			StockWhiteDTO stockWhiteDTO = StockWhiteDTO.builder()
					.masterId(masterId)
					.workCityId(masterStockQueryBO.getCityId())
					.build();
			boolean whiteByAllConditions = this.isWhiteByAllConditions(stockWhiteDTO);
			if (whiteByAllConditions) {
				stockWhiteMasterIdList.add(masterId);
			}
		}

		if (CollectionUtil.isNullOrEmpty(stockWhiteMasterIdList)) {
			return masterStockMap;
		}

		LocalDate dutyTime = LocalDate.parse(DateUtil.toString(masterStockQueryBO.getDutyTime(), DateUtil.FORMAT_DATE), DateTimeFormatter.ofPattern(DateUtil.FORMAT_DATE));
		List<List<Integer>> partition = Lists.partition(stockWhiteMasterIdList, 200);
		EngineerStockItemDIO engineerStockItemDIO = new EngineerStockItemDIO();
		engineerStockItemDIO.setDate(dutyTime);
		engineerStockItemDIO.setProductGroupCode(productGroupCode);
		engineerStockItemDIO.setProductNum(masterStockQueryBO.getProductNumber());
		try {
			for (List<Integer> masterIdList : partition) {
				log.info("stockListRemoteService.listStockByEngineerIdListAndProduct engineerStockItemDIO={},masterIdList={}", engineerStockItemDIO, masterIdList);
				ResponseDTO<List<EngineerStockItemDRO>> listResponseDTO = stockListRemoteService.listStockByEngineerIdListAndProduct(engineerStockItemDIO, masterIdList);
				log.info("stockListRemoteService.listStockByEngineerIdListAndProduct listResponseDTO={}", listResponseDTO);
				if (CollectionUtil.isNullOrEmpty(listResponseDTO.getData())) {
					continue;
				}
				for (EngineerStockItemDRO engineerStockItemDRO : listResponseDTO.getData()) {
					masterStockMap.put(engineerStockItemDRO.getEngineerId(), engineerStockItemDRO.getStockItemDRO());
				}
			}
		} catch (Exception e) {
			log.info("stockListRemoteService.listStockByEngineerIdListAndProduct error={}", e);
		}

		return masterStockMap;
	}

	@Override
	public List<StockUsedOrderDetailDRO> getStockUserOrderDetailByQuery(Integer engineerId, String startDate, String endDate) {
		StockUsedQuery query = StockUsedQuery
				.builder()
				.engineerId(engineerId)
				.startDate(startDate)
				.endDate(endDate)
				.build();
		log.info("#stockListRemoteService#listStockUsedOrderDetail入参：{}", JSON.toJSONString(query));
		ResponseDTO<List<StockUsedOrderDetailDRO>> listResponseDTO = stockListRemoteService.listStockUsedOrderDetail(query);
		log.info("#stockListRemoteService#listStockUsedOrderDetail出参：{}", JSON.toJSONString(listResponseDTO));
		if (listResponseDTO.isSuccess() && CollectionUtil.isNotNullOrEmpty(listResponseDTO.getData())) {
			return listResponseDTO.getData();
		}
		return Lists.newArrayList();
	}

	@Override
	public List<StockUsedOrderDetailDRO> getStockUserOrderDetailByEngineerId(Integer engineerId) {
		log.info("#stockListRemoteService#listTodayStartAllStockUsedOrderDetail入参：{}", engineerId);
		ResponseDTO<List<StockUsedOrderDetailDRO>> listResponseDTO = stockListRemoteService.listTodayStartAllStockUsedOrderDetail(engineerId);
		log.info("#stockListRemoteService#listTodayStartAllStockUsedOrderDetail出参：{}", JSON.toJSONString(listResponseDTO));
		if (listResponseDTO.isSuccess() && CollectionUtil.isNotNullOrEmpty(listResponseDTO.getData())) {
			return listResponseDTO.getData();
		}
		return Lists.newArrayList();
	}

	@Override
	public Boolean checkServTimeCanChang(Integer engineerId,Long sourceOrderId, Long targetOrderId) {
        log.info("#stockListRemoteService#checkServTimeCanChange入参：engineerId={},sourceOrderId={},targetOrderId={}", engineerId, sourceOrderId, targetOrderId);
        ResponseDTO<Boolean> responseDTO = stockListRemoteService.checkServTimeCanChange(engineerId, String.valueOf(sourceOrderId), String.valueOf(targetOrderId));
		log.info("#stockListRemoteService#checkServTimeCanChange出参：{}", JSON.toJSONString(responseDTO));
		if (responseDTO.isSuccess() && Objects.nonNull(responseDTO.getData())) {
			return responseDTO.getData();
		}
		return Boolean.FALSE;
	}

	@Override
	public Boolean exChangeTwoOrderServTime(Integer engineerId, Long sourceOrderId, Long targetOrderId,String operator) {
		operator = Optional.ofNullable(operator).orElse(GlobalConsts.getOperatorTypeName(GlobalConsts.OPERATE_USER_TYPE_SYSTEM));
		log.info("#stockModifyRemoteService#changeOrderServTimeByQuery入参：engineerId={},sourceOrderId={},targetOrderId={},operator={}", engineerId, sourceOrderId, targetOrderId, operator);
        ResponseDTO<Boolean> responseDTO = stockModifyRemoteService.changeOrderServTimeByQuery(engineerId, String.valueOf(sourceOrderId), String.valueOf(targetOrderId), operator);
        log.info("#stockModifyRemoteService#changeOrderServTimeByQuery出参：{}", JSON.toJSONString(responseDTO));
        if (responseDTO.isSuccess() && Objects.nonNull(responseDTO.getData())) {
            return responseDTO.getData();
        }
		return Boolean.FALSE;
	}
}
